[Swift] Swift製WebフレームワークVaporを使用してファイルアップロード API を作成する
はじめに
こんばんは。モバイルアプリサービス部の平屋です。
以下の記事でNode.js + express + Multerでファイルアップロード API を作成する手順を紹介しました。
同じ機能を持つアプリを、Swift製WebフレームワークVaporを使用して作成してみましたので、その手順を紹介していきます。
検証環境
- macOS Sierra 10.12.3
- Xcode 8.2.1
- Homebrew 1.1.1
- swiftenv 1.2.1
- Swift Snapshot DEVELOPMENT-SNAPSHOT-2017-03-09-a
- Vapor Toolbox 1.0.5
環境構築
以下の記事と同じ手順でswiftenvとVapor Toolboxを使用して環境を構築しました。
Vaporで始めるサーバーサイドSwift 〜Mac上での環境構築からHello, World!まで〜 (swiftenv, Vapor Toolboxを使用)
環境が構築できたら、vaporコマンドを使用してサーバーサイドアプリのプロジェクトを作成します。
$ vapor new vapor-multipart-formdata-sample
main.swiftを修正
プロジェクトのSources/Appディレクトリ内のmain.swiftを修正して、POSTリクエストを受け付けられるようにします。
以下のように、13-26行目を追加します。
import Vapor import Foundation let drop = Droplet() drop.get { req in return try drop.view.make("welcome", [ "message": drop.localization[req.lang, "welcome", "title"] ]) } // ここから drop.post { req in guard let field = req.formData?["file"] else { return JSON(["result":"receive failure"]) } do { let dest = URL(fileURLWithPath: field.filename!) try Data(field.part.body).write(to: dest) } catch { return JSON(["result":"save failure"]) } return JSON(["result":"success"]) } // ここまでを追加 drop.resource("posts", PostController()) drop.run()
14行目では、RequestオブジェクトのformData
プロパティからname
が"file"
のField構造体を取り出しています。Field構造体は、ファイル名やバイナリデータなどを持ちます。
19行目ではファイル名を取り出し、20行目では受け取ったデータをファイルとして保存しています。
動作確認
サーバーサイドアプリを実行
以下のコマンドを実行して、サーバーサイドアプリのビルドとサーバーの起動を行います。ポート8080でリクエストを受け付けるようになります。
$ vapor build $ vapor run serve
iOS アプリからファイルをアップロードする
iOS アプリの場合、以下のような実装でファイルをアップロードできます。
iOS + Swift + Alamofire
func upload() { let path = Bundle.main.path(forResource: "image", ofType: "png") let fileURL = URL.init(fileURLWithPath: path!) Alamofire.upload( multipartFormData: { multipartFormData in multipartFormData.append(fileURL, withName: "file") }, to: "http://192.168.0.11:8080/", encodingCompletion: { encodingResult in switch encodingResult { case .success(let upload, _, _): upload.responseJSON { response in debugPrint(response) } case .failure(let encodingError): print(encodingError) } } ) }
iOS + Objective-C + AFNetworking
- (void)upload { NSString *path = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"png"]; NSURL *fileURL = [NSURL fileURLWithPath:path]; AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; [manager POST:@"http://192.168.0.11:8080" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileURL:fileURL name:@"file" error:nil]; } progress:nil success:^(NSURLSessionTask *task, id responseObject) { NSLog(@"success"); } failure:^(NSURLSessionTask *task, NSError *error) { NSLog(@"error:%@", error.localizedDescription); }]; }
動作結果
iOS アプリからアップロード操作を行い、サーバーサイドアプリのルートディレクトリにファイルがアップロードされることを確認できました。
さいごに
本記事ではSwift製WebフレームワークVaporを使用してファイルアップロード API を作成する手順を紹介しました。
以前作成したNode.js版のものと同じぐらい簡単に作れることがわかりました。
今回解説したサンプルアプリケーションは以下のリポジトリで公開しています。
参考資料
- Vapor
- Vapor Documentation
- vapor/multipart
- Vaporで始めるサーバーサイドSwift 〜Mac上での環境構築からHello, World!まで〜 (swiftenv, Vapor Toolboxを使用)
- Installation — swiftenv 1.1.0 documentation
- Swift.org - Download Swift
- Uploading files using Vapor - Stack Overflow
- xcode - Swift 3 How To Send A Multipart Post Request With Vapor - Stack Overflow
- vapor swift file upload - Stack Overflow
- リクエストとレスポンスの仕組み